import copy
from qtpy import QtGui
from qtpy import QtCore
from utils import DrawType
from utils import calc_distance
from utils import calc_distancetoline
from enum import Enum


class Shape(object):
    class VertexType(Enum):
        # 顶点的形状
        SQUARE = 0  # 方形
        ROUND = 1  # 圆形
    point_size = 4
    scale = 1.0

    def __init__(self, label=None, color=(255, 255, 255, 150), shape_type=None, group_id=None, attributes={}):
        self.label = label
        self.color = color
        self.point_list = []
        self.shape_type = shape_type
        self.group_id = group_id,
        self.attributes = attributes
        # 默认描画圆形顶点
        self.vertex_type = self.VertexType.ROUND
        # 当前是否被选中
        self.selected = False
        self.fill = False
        self._closed = False
        # 高亮的顶点
        self.highlight_vertex_index = None

    def __makePath(self):

        if self.shape_type == DrawType.DRAW_TYPE_RECT.value:
            path = QtGui.QPainterPath()
            if len(self.point_list) == 2:
                rectangle = self.__getRect(*self.point_list)
                path.addRect(rectangle)
        else:
            pass
        return path

    def __getRect(self, pt1, pt2):
        """根据左上右下两个点获取矩形对象"""
        x1, y1 = pt1.x(), pt1.y()
        x2, y2 = pt2.x(), pt2.y()
        return QtCore.QRectF(x1, y1, x2 - x1, y2 - y1)

    def __drawVertex(self, path, i):
        d = self.point_size / self.scale
        vertex_type = self.vertex_type
        point = self.point_list[i]
        if i == self.highlight_vertex_index:
            d *= 2.0
            vertex_type = self.VertexType.SQUARE
        if vertex_type == self.VertexType.ROUND:
            # 描画圆形
            path.addEllipse(point, d / 2.0, d / 2.0)
        elif vertex_type == self.VertexType.SQUARE:
            # 描画方形
            path.addRect(point.x() - d / 2, point.y() - d / 2, d, d)
        else:
            pass

    def canAddPoint(self):
        if (self.shape_type == DrawType.DRAW_TYPE_POLYGON.value or
            self.shape_type == DrawType.DRAW_TYPE_LINE.value):
            return True
        else:
            return False

    def move(self, offset):
        self.point_list = [point + offset for point in self.point_list]

    def moveVertex(self, index, offset):
        self.point_list[index] = self.point_list[index] + offset

    def containsPoint(self, point):
        return self.__makePath().contains(point)

    def addPoint(self, point):
        """添加形状点"""
        if self.point_list and point == self.point_list[0]:
            self.setClose()
        else:
            self.point_list.append(point)

    def selectVertex(self):
        return self.highlight_vertex_index is not None

    def highlightVertex(self, index):
        self.highlight_vertex_index = index

    def cancelHighlightVertex(self):
        self.highlightVertex(None)

    def nearestVertex(self, point, min_dis):
        min_distance = float("inf")
        min_i = None
        for i, p in enumerate(self.point_list):
            dist = calc_distance(p, point)
            if dist <= min_dis and dist < min_distance:
                min_distance = dist
                min_i = i
        return min_i

    def nearestEdge(self, point, min_dis):
        min_distance = float("inf")
        post_i = None
        for i in range(len(self.point_list)):
            line = [self.point_list[i - 1], self.point_list[i]]
            dist = calc_distancetoline(point, line)
            if dist <= min_dis and dist < min_distance:
                min_distance = dist
                post_i = i
        return post_i

    def isClosed(self):
        return self._closed

    def setClose(self):
        self._closed = True

    def setOpen(self):
        self._closed = False

    def paint(self, painter):
        line_color = QtGui.QColor(*self.color[:3], 220)
        point_color = QtGui.QColor(*self.color[:3])
        fill_color = QtGui.QColor(*self.color)
        # print(line_color.red(),line_color.green(),line_color.blue())
        # print(point_color.red(),point_color.green(),point_color.blue())
        # print(fill_color.red(),fill_color.green(),fill_color.blue())
        if self.point_list:
            if self.selected:
                pen = QtGui.QPen(QtGui.QColor(255, 255, 255), 1.5, QtCore.Qt.SolidLine)
            else:
                pen = QtGui.QPen(line_color, 1.5, QtCore.Qt.SolidLine)
            pen.setWidth(max(1, int(round(2.0 / self.scale))))
            painter.setPen(pen)
            line_path = QtGui.QPainterPath()
            vrtx_path = QtGui.QPainterPath()

        if self.shape_type == DrawType.DRAW_TYPE_RECT.value:
            if len(self.point_list) == 2:
                line_path.addRect(self.__getRect(*self.point_list))
                for i in range(len(self.point_list)):
                    self.__drawVertex(vrtx_path, i)
        else:
            line_path.moveTo(self.point_list[0])
            for i, p in enumerate(self.point_list):
                line_path.lineTo(p)
                self.__drawVertex(vrtx_path, i)
            if self.isClosed():
                line_path.lineTo(self.point_list[0])

        painter.drawPath(line_path)
        painter.drawPath(vrtx_path)
        painter.fillPath(vrtx_path, point_color)
        if self.fill:
            painter.fillPath(line_path, fill_color)

    def copy(self):
        return copy.deepcopy(self)

    def __len__(self):
        return len(self.point_list)

    def __getitem__(self, key):
        return self.point_list[key]

    def __setitem__(self, key, value):
        self.point_list[key] = value
